import socket
import time
import threading
import sqlite3

HOST = "127.0.0.1"
PORT = 9895

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen()

clients = []
names = []
names_n = []


def broadcast(message, clientn,clientnow=None):
    if clientnow == None:
        for client in clientn:
            client.send(message)
        return
    name_i = names[clientn.index(clientnow)]
    clientn.remove(clientnow)
    names.remove(name_i)
    for client in clientn:
        client.send(message)
    clientn.insert(0,clientnow)
    names.insert(0,name_i)
def h_client(client, address,msg):
    clients.append(client)
    print(f"Connected with {str(address)}!")
    client.send("[INFO]client success".encode('utf-8'))
    name_password = msg
    print(name_password)
    name_a_password = []
    name_a_password = name_password[6:].split(':')
    name = name_a_password[0]
    password = name_a_password[1]
    print(name,' ',password)
    if is_password_correct(name, password):
        names.append(name)
        names_n.append(name)
        broadcast(f"[MSGS]加入聊天 {name}".encode('utf-8'), clients, client)
        print(f"{name} has joined the chat!")
        client.send("[INFO]login success".encode('utf-8'))
    else:
        client.send("[INFO]login failed".encode('utf-8'))
        return

def is_password_correct(username, password):
    try:
        with sqlite3.connect('./user.db') as sqld:
            cursor = sqld.cursor()
            cursor.execute("SELECT * FROM user WHERE name = ?", (username,))
            result = cursor.fetchall()
            if len(result) == 1 and result[0][1] == password:
                try:
                    flag = True
                    for i in names:
                        if i == username:
                            flag = False
                            break
                    if flag:
                        names.append(username)
                        return True
                    else:
                        return False
                except:
                    return False
            else:
                return False
    except Exception as e:
        print(f"Error validating password: {e}")
        return False
def create_user(username, password):
    sql = sqlite3.connect('./user.db')
    cursor = sql.cursor()
    try:
        cursor.execute("INSERT INTO user (name, password) VALUES (?, ?)", (username, password))
    except:
        cursor.rollback()
        return False
    return True
def handle(client, address):
    while True:
        msg = client.recv(1024).decode('utf-8')
        code = msg[:6]
        if len(msg) !=0:
            print(msg)
        if code == "[LOIN]":
            threading.Thread(target=h_client, args=(client, address,msg)).start()
        elif code == "[MSGS]":
            threading.Thread(target=broadcast, args=(msg.encode('utf-8'), clients,client)).start()
        elif code == "[INFO]":
            print(msg)
        elif code == "[EXIT]":
            name = names[clients.index(client)]
            print(f"{name} has left the chat!")
            clients.remove(client)
            names.remove(name)
            threading.Thread(target=broadcast, args=(f"[MSGS]离开聊天 {name}".encode('utf-8'), clients)).start()
            names_n.remove(name)
            client.close()
            break
        now = time.time()
        sql = sqlite3.connect('./data.db')
        cursor = sql.cursor()
        cursor.execute("INSERT INTO msgdata (msg, time) VALUES (?,?)", (msg, now))
        sql.commit()
        sql.close()


print("[STARTING] server is starting...")

def name_send():
    HOST2 = "127.0.0.1"
    PORT2 = 9896

    s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s2.bind((HOST2, PORT2))
    s2.listen()
    while True:
        clientnow, address = s2.accept()
        threading.Thread(target=name_handle, args=(clientnow, address)).start()

def name_handle(clientnow, address):
    global names,names_n
    print(f"Name Server Connected with {str(clientnow)}!")
    while True:
        msg = clientnow.recv(1024).decode('utf-8')
        if msg == "[INFO]Get Names":
            Names = ''
            for i in names_n:
                Names = Names + i + ':'
            clientnow.send(Names.encode('utf-8'))
        elif msg == "[EXIT]":
            clientnow.close()
            break


threading.Thread(target=name_send).start()

while True:
    clientnows, address = s.accept()
    threading.Thread(target=handle, args=(clientnows, address)).start()